/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

import IconFontExtend from '@base/components/iconFont';
import { isArray } from 'lodash';
import React, { CSSProperties, useMemo, useRef } from 'react';
import { matchPath, RouteProps } from 'react-router';
import type { Location } from 'umi';
import { history, Link, useLocation } from 'umi';
import { flattenDeepList } from '../utils';
import { compareWindowSize, useWindowSizeChange, WinSize, winSizeMap } from './win';

export interface BodyZoomOptions {
  fix: number;
  min: WinSize;
  max: WinSize;
}

export type RoutesItemPlacement = 'left' | 'right';
export interface RoutesItemOther {
  key?: string;
  label?: string | React.ReactNode;
  routes?: Routes;
  layout?: boolean;
  staticHeader?: boolean;
  affixHeader?: boolean;
  hideInMenu?: boolean;
  showInFooter?: boolean;
  href?: string;
  title?: string;
  name?: string;
  placement?: RoutesItemPlacement;
  access?: string;
  className?: string;
  parentKeys?: string[];
  icon?: string | React.ReactNode;
  unlink?: boolean;
}
export type RoutersItem = RouteProps & RoutesItemOther;
export type Routes = RoutersItem[];

export function useBodyZoom(opts?: BodyZoomOptions) {
  const { fix = 48, min = 'sm', max = 'xl' } = opts || {};
  const actionRef = useRef<{ timer?: NodeJS.Timeout }>({});
  useWindowSizeChange(({ size }) => {
    if (size) {
      const compareSm = compareWindowSize(min); // 缩到sm；
      const compareXl = compareWindowSize(max, fix); // 缩到xl；
      const zoom = parseFloat(
        new Number(compareSm >= 0 || compareXl < 0 ? 1 : size / (winSizeMap.xl + fix)).toFixed(6),
      );
      clearTimeout(actionRef.current.timer);
      actionRef.current.timer = setTimeout(() => {
        const bodyStyle = document.body.style as CSSProperties;
        bodyStyle.zoom = zoom;
      }, 100);
    }
  });
}

/**
 *
 * @description 判断是否需要layout
 * @param routes
 * @returns
 */
export function useLayout(routes: Routes) {
  const { layout } = useCurrentRouter(routes);
  return [layout];
}

/**
 *
 * @description 菜单列表
 * @param routes
 * @returns
 */
export interface MenuItemType {
  key: string;
  label: string | React.ReactNode;
  title?: string;
  path?: string;
  href?: string;
  icon?: string | React.ReactNode;
  staticHeader?: boolean;
  className?: string;
  popupClassName?: string;
  children?: MenuItemType[] | null;
}
type Filter = (item: RoutersItem) => boolean;

/**
 *
 * @descriptions 过滤菜单项
 * @param item
 * @param filter
 * @returns
 */
function filterRoutes(item: RoutersItem, filter?: Filter) {
  const { title, name = title, hideInMenu, path } = item;
  return name && !hideInMenu && path && !path.includes('.html') && (!filter ? true : filter(item));
}

/**
 *
 * @descriptions 格式化菜单选项
 * @param param0
 * @returns
 */
function formatMenusItem({
  href,
  path = href,
  title,
  name = title,
  className,
  routes,
  unlink,
  icon,
  key,
}: RoutersItem): MenuItemType {
  const item: MenuItemType = {
    key: key || (path as string),
    title: name,
    label: unlink ? (
      name
    ) : href ? (
      <a href={href} target='_blank' rel='noreferrer'>
        {name}
      </a>
    ) : (
      <Link to={path as string}>{name}</Link>
    ),
    path: path as string,
    href,
    className,
  };
  if (icon) {
    item.icon = <IconFontExtend type={icon as string} />;
  }

  if (!routes) {
    return item;
  }
  const children = routes.filter((i) => filterRoutes(i)).map(formatMenusItem);
  if (children.length === 0) {
    return item;
  }
  return {
    ...item,
    popupClassName: 'submenu-popup-fixed',
    children,
  };
}

/**
 *
 * @descriptions 头部导航风格 staticHeader：头部没有图时一般采用static定位，默认为false；affixHeader：是否滚动时固定头部，默认为true；
 * @param location
 * @param routes
 * @returns
 */
export function getCurrentRouter(location: Location, routes: Routes): RoutersItem {
  const { pathname } = location;
  const router = routes.find(
    (item) => pathname && (pathname === item.path || matchPath(pathname, item)),
  );
  return { staticHeader: !router, affixHeader: true, layout: true, ...router };
}

/**
 *
 * @descriptions 深入查找当前router
 * @param pathname
 * @param routes
 * @returns
 */
export function getCurrentRouterDeep(pathname: string, routes: Routes): RoutersItem {
  const currentRouter = getCurrentRouter({ pathname } as Location, routes);
  const { routes: currentRoutes } = currentRouter;
  if (isArray(currentRoutes)) {
    return getCurrentRouterDeep(pathname, currentRoutes);
  }
  return currentRouter;
}

/**
 *
 * @descriptions 获取选中与打开的keys
 */
export function getSelectAndOpenKeys(pathname: string, routes?: Routes): [string[], string[]] {
  const paths = pathname.split('/');
  const keys = paths.map((_, i) => paths.slice(0, i + 1).join('/')).filter((pi) => !!pi);
  const s = keys;
  const o = keys.slice(0, -1);
  if (routes) {
    const { key = '', parentKeys = [] } = getCurrentRouterDeep(pathname, routes);
    const ss = [...s, key, ...parentKeys].filter((si) => !!si);
    return [ss, o];
  }
  return [s, o];
}

/**
 *
 * @descriptions hooks routes整理成menus
 * @param routes
 * @param filter
 * @param filterOnly
 * @returns
 */
export function useMenus(
  routes: Routes,
  filter?: Filter,
  filterOnly?: Filter,
): [MenuItemType[], (e: any) => void, string[], string[]] {
  const location = useLocation<Location>();
  const { pathname } = location;

  const menus: MenuItemType[] = useMemo(() => {
    return routes
      .filter((item) => {
        if (filterOnly) {
          return filterOnly(item);
        }
        return filterRoutes(item, filter);
      })
      .map(formatMenusItem);
  }, [routes, filterOnly, filter]);

  const handleSelect = (e: any) => {
    const { key } = e;
    const menuItem = menus.find((item) => item.path === key);
    const href = menuItem?.href;
    if (href) {
      window.open(href);
      return;
    }
    history.push(key);
  };

  const [selectedKeys, openKeys] = useMemo(
    () => getSelectAndOpenKeys(pathname, routes),
    [pathname],
  );

  return [menus, handleSelect, selectedKeys, openKeys];
}

/**
 *
 * @descriptions hooks 获取当前导航
 * @param routes
 * @returns
 */
export function useCurrentRouter(routes: Routes): RoutersItem {
  const location: Location = useLocation();
  const currentRouter = useMemo(() => getCurrentRouter(location, routes), [location, routes]);
  return currentRouter;
}

interface BreadcrumbOptions {
  menus: MenuItemType[];
  route: RoutersItem;
}

/**
 *
 * @descriptions hooks 面包屑
 * @param opts
 * @returns
 */
export function useBreadcrumb(opts: BreadcrumbOptions): RoutersItem[] {
  const { menus, route } = opts;

  const location = useLocation<Location>();
  const breadcrumbs = useMemo(() => {
    const { pathname } = location;

    let paths = pathname.split('/');
    paths = paths.map((_, i) => paths.slice(0, i + 1).join('/')).filter((i) => !!i);
    if (paths) {
      return [
        ...paths
          .map((p) =>
            flattenDeepList([route, ...menus], 'children')
              .map(({ key, path = key, label, title = label, ...rest }) => ({
                ...rest,
                path,
                title,
              }))
              .find((item) => item.path === p),
          )
          .filter((item) => !!item),
      ];
    }
    return [];
  }, [location, menus]);

  return breadcrumbs as RoutersItem[];
}
